Updates to LRO samples for Agent Optimization, Dataset Generation & Evaluator Job - #48343
Conversation
|
Azure Pipelines: Successfully started running 1 pipeline(s). 9 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Updates Azure AI Projects samples to expose standard LRO polling progress and capture service error details.
Changes:
- Reports polling and terminal statuses.
- Captures LRO responses for failure messages.
- Converts optimization polling samples to standard pollers.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py |
Adds polling for lifecycle and replay jobs. |
samples/evaluations/sample_rubric_evaluator_generation_iterate.py |
Adds polling for iterative generation. |
samples/evaluations/sample_rubric_evaluator_generation_basic.py |
Adds polling for basic generation. |
samples/evaluations/sample_rubric_evaluator_generation_all_sources.py |
Adds polling for multi-source and trace jobs. |
samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py |
Adds polling for fine-tuning trace generation. |
samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py |
Adds polling for evaluation trace generation. |
samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py |
Adds polling for prompt-based generation. |
samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py |
Adds polling for file-based generation. |
samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py |
Adds polling for agent-based generation. |
samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py |
Adds polling for fine-tuning data generation. |
samples/agents/optimization/sample_optimization_job_basic.py |
Updates built-in polling documentation. |
samples/agents/optimization/sample_optimization_job_basic_polling.py |
Replaces manual polling with an LRO poller. |
samples/agents/optimization/sample_optimization_job_basic_polling_async.py |
Replaces async manual polling with an LRO poller. |
samples/agents/optimization/sample_optimization_job_basic_async.py |
Updates async polling documentation. |
Comments suppressed due to low confidence (4)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:159
- When background polling fails,
done()only indicates that the poller thread stopped; it does not guarantee a terminal service response. Since this branch never callsresult(), it hides the poller's HTTP/transport exception and may claim the replay ended in a stale nonterminal status. Observe and chain that exception before raising the custom message.
if replay_status.lower() != "succeeded":
error = latest_replay_lro_response.get("error")
message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
raise RuntimeError(f"Replay job ended with status `{replay_status}`: {message}")
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:228
done()becomes true if the synchronous poller thread exits on an HTTP/transport exception as well as on normal completion. Because this branch never callsresult(), it loses that exception and may misleadingly report a stale nonterminal status. Observe and chain the poller exception before raising the custom message.
if status.lower() != "succeeded":
error = latest_lro_response.get("error")
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling.py:117
- This conversion drops the sample's previous reporting of
OptimizationJob.warnings. The LRO returns onlyOptimizationJobResult, which has no warnings field, so non-fatal service advisories are silently discarded even though the raw terminal job response is already captured. Preserve and print itswarningsbefore moving on to the result.
result = poller.result()
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling_async.py:124
- This conversion drops the sample's previous reporting of
OptimizationJob.warnings. The LRO returns onlyOptimizationJobResult, which has no warnings field, so non-fatal service advisories are silently discarded even though the raw terminal job response is already captured. Preserve and print itswarningsbefore moving on to the result.
result = await result_task
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (16)
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling_async.py:107
- If the polling coroutine raises (for example, when the service reports
FailedorCanceled),AsyncLROPoller.wait()exits before setting its internal_doneflag. The task is then complete with an exception, but this loop continues forever and never reaches the code that awaits and wraps that exception. Poll the task's completion instead.
while not poller.done():
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:153
- This replay loop also only observes a sync
LROPollerwhose Azure Core background thread is doing the actual polling, so it does not restore application-managed polling as described. Disable SDK polling and explicitly fetch the replay job status instead.
while not replay_poller.done():
print(f"Replay job status: {replay_poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:224
- This traces loop likewise only watches a sync
LROPollerwhile its Azure Core background thread performs the requests. It does not demonstrate polling outside the SDK as described. Disable SDK polling and explicitly fetch the traces job status.
while not poller.done():
print(f"Traces job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:14
- The continuation text is over-indented relative to the bullet, so the rendered sample description no longer aligns with the other list entries.
returns `LROPoller[EvaluatorVersion]`, whose status is reported until
the job reaches a terminal state.
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:137
- This loop only observes the sync
LROPoller; constructing that poller has already started Azure Core's background polling thread. It therefore does not demonstrate the application-managed polling described in the PR. Disable SDK polling and explicitly fetch the generation job status if this sample is meant to restore polling outside the SDK.
This issue also appears on line 151 of the same file.
while not poller.done():
print(f"Generation job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_iterate.py:110
- A sync
LROPollerbegins polling on an Azure Core background thread as soon as it is constructed; this loop merely reports that thread's status. Consequently this sample still uses SDK polling rather than the application-managed polling promised by the PR description. Disable SDK polling and explicitly retrieve the job status.
while not poller.done():
print(f"Generation job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_basic.py:134
- A sync
LROPollerstarts Azure Core's polling thread during construction, so this loop only observes SDK polling; it does not perform polling outside the SDK as the PR description says. Disable SDK polling and explicitly retrieve the generation job status for an application-polling example.
while not poller.done():
print(f"Generation job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:156
- This loop only monitors a sync
LROPoller; Azure Core starts a background polling thread when that poller is constructed. The sample therefore still relies on SDK polling instead of demonstrating the application-managed polling stated in the PR description. Disable SDK polling and fetch the multi-source job status explicitly.
This issue also appears on line 222 of the same file.
while not poller.done():
print(f"Multi-source job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py:177
- Constructing this sync
LROPolleralready starts Azure Core's polling thread, so this loop merely reports SDK-managed polling. That contradicts the PR's stated goal of restoring polling outside the SDK. Disable SDK polling and explicitly fetch the data-generation job status.
while not poller.done():
print(f"Data generation job status: {poller.status()}")
time.sleep(POLL_INTERVAL_SECONDS)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py:174
- Constructing this sync
LROPolleralready starts Azure Core's polling thread, so this loop merely reports SDK-managed polling. That contradicts the PR's stated goal of restoring polling outside the SDK. Disable SDK polling and explicitly fetch the data-generation job status.
while not poller.done():
print(f"Data generation job status: {poller.status()}")
time.sleep(POLL_INTERVAL_SECONDS)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py:138
- This loop does not itself poll the service: the sync
LROPollerstarted an Azure Core background polling thread when it was created. The sample therefore still demonstrates SDK polling, contrary to the PR description's application-polling goal. Disable SDK polling and explicitly retrieve the job status.
while not poller.done():
print(f"Data generation job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py:200
- This loop does not itself poll the service: the sync
LROPollerstarted an Azure Core background polling thread when it was created. The sample therefore still demonstrates SDK polling, contrary to the PR description's application-polling goal. Disable SDK polling and explicitly retrieve the job status.
while not poller.done():
print(f"Data generation job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py:180
- This loop only observes the sync
LROPoller; Azure Core is already polling in its background thread. As written, the sample does not restore application-managed polling as claimed in the PR description. Disable SDK polling and explicitly retrieve the data-generation job status.
while not poller.done():
print(f"Data generation job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py:189
- The sync
LROPollerstarts Azure Core's background polling thread during construction, so this loop only reports SDK polling. It does not implement the application-managed polling described by the PR. Disable SDK polling and explicitly fetch the fine-tuning generation job status.
while not poller.done():
print(f"Data generation job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling.py:106
- This loop only monitors the sync
LROPoller; Azure Core has already started polling on a background thread. The change therefore replaces the prior application-managed job polling with SDK polling, opposite to the PR description. Keep polling disabled and explicitly callget_optimization_jobuntil terminal.
while not poller.done():
print(f"Optimization job status: {poller.status()}")
time.sleep(poll_interval)
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling_async.py:109
- Creating a task from
poller.result()explicitly starts Azure Core's async polling loop; the surrounding loop only observes it. This changes the previous application-managed optimization-job polling into SDK-managed polling, contrary to the PR description. Keep SDK polling disabled and explicitly retrieve the job status.
result_task = asyncio.create_task(poller.result())
while not poller.done():
print(f"Optimization job status: {poller.status()}")
await asyncio.sleep(poll_interval)
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (16)
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling_async.py:109
AsyncLROPoller.done()is set only afterwait()returns successfully. If the LRO fails,result_taskcompletes with an exception butpoller.done()remains false, so this loop sleeps forever and the failure handling below is never reached. Use the task's completion state as the loop condition.
result_task = asyncio.create_task(poller.result())
while not poller.done():
print(f"Optimization job status: {poller.status()}")
await asyncio.sleep(poll_interval)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:14
- The added indentation makes these continuation lines render far to the right of the surrounding bullet text instead of aligning with it.
returns `LROPoller[EvaluatorVersion]`, whose status is reported until
the job reaches a terminal state.
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:153
- This replay loop also only observes the synchronous
LROPoller's background SDK polling; callingdone()does not perform an application poll. It therefore does not demonstrate the application-managed polling promised by the PR.
while not replay_poller.done():
print(f"Replay job status: {replay_poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:224
- This second synchronous loop likewise only observes the
LROPoller's background SDK polling. It does not issue application-level status requests and therefore does not demonstrate the polling mode described in the PR.
while not poller.done():
print(f"Traces job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:137
- This does not implement the application-managed polling described by the PR. A synchronous
LROPollerstarts its SDK polling thread during construction (azure-core/.../_poller.py:228-240), sodone()andstatus()only observe SDK-managed polling. Usepolling=Falseplus explicitget_generation_jobcalls between sleeps, or revise the sample's stated purpose.
This issue also appears on line 151 of the same file.
while not poller.done():
print(f"Generation job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_iterate.py:110
- A synchronous
LROPollerbegins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; usepolling=Falseand explicit status retrieval between sleeps.
while not poller.done():
print(f"Generation job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_basic.py:134
- A synchronous
LROPollerbegins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; usepolling=Falseand explicit status retrieval between sleeps.
while not poller.done():
print(f"Generation job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:156
- A synchronous
LROPollerbegins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; usepolling=Falseand explicit status retrieval between sleeps.
This issue also appears on line 222 of the same file.
while not poller.done():
print(f"Multi-source job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py:177
- A synchronous
LROPollerbegins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; usepolling=Falseand explicit status retrieval between sleeps.
while not poller.done():
print(f"Data generation job status: {poller.status()}")
time.sleep(POLL_INTERVAL_SECONDS)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py:174
- A synchronous
LROPollerbegins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; usepolling=Falseand explicit status retrieval between sleeps.
while not poller.done():
print(f"Data generation job status: {poller.status()}")
time.sleep(POLL_INTERVAL_SECONDS)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py:138
- A synchronous
LROPollerbegins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; usepolling=Falseand explicit status retrieval between sleeps.
while not poller.done():
print(f"Data generation job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py:200
- A synchronous
LROPollerbegins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; usepolling=Falseand explicit status retrieval between sleeps.
while not poller.done():
print(f"Data generation job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py:180
- A synchronous
LROPollerbegins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; usepolling=Falseand explicit status retrieval between sleeps.
while not poller.done():
print(f"Data generation job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py:189
- A synchronous
LROPollerbegins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; usepolling=Falseand explicit status retrieval between sleeps.
while not poller.done():
print(f"Data generation job status: {poller.status()}")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling.py:106
- This replaces the prior
polling=Falseplusget_optimization_jobapplication polling with the default synchronousLROPoller, which starts SDK polling in a background thread during construction. The loop therefore only observes SDK polling and makes this sample another built-in-polling example, contrary to the PR's stated separation between the basic and polling samples.
while not poller.done():
print(f"Optimization job status: {poller.status()}")
time.sleep(poll_interval)
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling_async.py:109
- Creating a task for
poller.result()starts the async SDK polling loop (azure-core/.../_async_poller.py:230-258); the surrounding loop merely reports its status. This converts the polling sample into another SDK-managed-polling example instead of preserving the application-managed polling that the PR description says should remain distinct.
result_task = asyncio.create_task(poller.result())
while not poller.done():
print(f"Optimization job status: {poller.status()}")
await asyncio.sleep(poll_interval)
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (28)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:130
- The replay call also leaves
polling=True, so this second synchronousLROPollerstarts another SDK polling thread immediately. The subsequentdone()/status()loop observes SDK polling rather than performing the application-controlled polling described by the PR.
replay_poller = project_client.beta.evaluators.begin_create_generation_job(
job=job_body,
operation_id=operation_id,
polling_interval=poll_interval_seconds,
raw_response_hook=capture_replay_lro_response,
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:197
- The traces path likewise leaves SDK polling enabled. The synchronous
LROPollerstarts polling as soon as it is constructed, so this path only reports SDK-managed progress instead of demonstrating application-controlled polling.
poller = project_client.beta.evaluators.begin_create_generation_job(
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:143
done()also becomes true when the background polling thread exits with an exception (azure/core/polling/_poller.py:242-261). If a polling request fails while the status is stillInProgress, this branch masks the stored SDK exception as “ended with status InProgress: ”; onlyresult()/wait()propagates the original exception. Surface the poller exception before interpreting a non-success status.
if status.lower() != "succeeded":
error = latest_lro_response.get("error")
message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
raise RuntimeError(f"Generation job ended with status `{status}`: {message}")
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_iterate.py:116
done()is also true when the polling thread exits with an exception. If a request fails while status remainsInProgress, this branch masks the stored SDK exception with “ended with status InProgress”;result()is the call that would propagate the real failure.
if status.lower() != "succeeded":
error = latest_lro_response.get("error")
message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
raise RuntimeError(f"Generation job ended with status `{status}`: {message}")
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:159
- The replay loop has the same exception path:
done()is true after the polling thread fails, whilestatus()may still beInProgress. Raising this custom error before callingresult()masks the underlying SDK polling exception and reports a false terminal status.
if replay_status.lower() != "succeeded":
error = latest_replay_lro_response.get("error")
message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
raise RuntimeError(f"Replay job ended with status `{replay_status}`: {message}")
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_basic.py:140
done()is also true when the polling thread exits with an exception. If a request fails while status remainsInProgress, this branch masks the stored SDK exception with “ended with status InProgress”;result()is the call that would propagate the real failure.
if status.lower() != "succeeded":
error = latest_lro_response.get("error")
message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
raise RuntimeError(f"Generation job ended with status `{status}`: {message}")
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:162
- A failed polling thread also makes
done()true. When a request exception leaves status asInProgress, this branch replaces the stored SDK exception with a misleading terminal-statusRuntimeError; callingresult()is what propagates the actual polling failure.
if status.lower() != "succeeded":
error = latest_lro_response.get("error")
message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
raise RuntimeError(f"Multi-source job ended with status `{status}`: {message}")
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py:144
done()is also true after the polling thread fails. If the failure occurs while status remainsInProgress, this branch masks the stored SDK exception with a false terminal-status error;result()would otherwise propagate the actual polling failure.
if status.lower() != "succeeded":
error = latest_lro_response.get("error")
message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
raise RuntimeError(f"Data generation job ended with status `{status}`: {message}")
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py:206
done()is also true after the polling thread fails. If the failure occurs while status remainsInProgress, this branch masks the stored SDK exception with a false terminal-status error;result()would otherwise propagate the actual polling failure.
if status.lower() != "succeeded":
error = latest_lro_response.get("error")
message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
raise RuntimeError(f"Data generation job ended with status `{status}`: {message}")
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py:186
done()is also true after the polling thread fails. If the failure occurs while status remainsInProgress, this branch masks the stored SDK exception with a false terminal-status error;result()would otherwise propagate the actual polling failure.
if status.lower() != "succeeded":
error = latest_lro_response.get("error")
message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
raise RuntimeError(f"Data generation job ended with status `{status}`: {message}")
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py:195
done()is also true after the polling thread fails. If the failure occurs while status remainsInProgress, this branch masks the stored SDK exception with a false terminal-status error;result()would otherwise propagate the actual polling failure.
if status.lower() != "succeeded":
error = latest_lro_response.get("error")
message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
raise RuntimeError(f"Data generation job ended with status `{status}`: {message}")
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:14
- These continuation lines are over-indented relative to the surrounding bullet list, so the module description renders as a malformed list item.
returns `LROPoller[EvaluatorVersion]`, whose status is reported until
the job reaches a terminal state.
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:228
- A failed polling thread also makes
done()true. When a request exception leaves status asInProgress, this branch replaces the stored SDK exception with a misleading terminal-statusRuntimeError; callingresult()is what propagates the actual polling failure.
if status.lower() != "succeeded":
error = latest_lro_response.get("error")
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py:181
done()becomes true when polling exits with an exception as well as on service completion. If a polling request fails while status is stillInProgress, this branch masks the SDK exception as a misleading terminal-status error instead of lettingresult()propagate the real cause.
if status.lower() != "succeeded":
error = latest_lro_response.get("error")
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py:178
done()becomes true when polling exits with an exception as well as on service completion. If a polling request fails while status is stillInProgress, this branch masks the SDK exception as a misleading terminal-status error instead of lettingresult()propagate the real cause.
if status.lower() != "succeeded":
error = latest_lro_response.get("error")
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:111
- This still uses SDK-managed polling: the default
polling=Trueconstructs a synchronousLROPoller, which starts its polling thread immediately (sdk/core/azure-core/azure/core/polling/_poller.py:225-240).done()andstatus()only observe that background poller, so this does not restore the application-controlled polling described by the PR. Disable SDK polling and fetch job status explicitly, as the optimization polling sample does, or revise the sample's stated purpose.
This issue also appears on line 126 of the same file.
poller = project_client.beta.evaluators.begin_create_generation_job(
job=job_body,
operation_id=operation_id,
polling_interval=poll_interval_seconds,
raw_response_hook=capture_lro_response,
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_iterate.py:84
- This still uses SDK-managed polling: the default synchronous
LROPollerstarts polling in a background thread at construction (sdk/core/azure-core/azure/core/polling/_poller.py:225-240). The new loop only reports that poller's state, rather than restoring the application-controlled polling described by the PR.
poller = project_client.beta.evaluators.begin_create_generation_job(
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_basic.py:101
- This still uses SDK-managed polling: the default synchronous
LROPollerstarts polling in a background thread at construction (sdk/core/azure-core/azure/core/polling/_poller.py:225-240). The new loop only reports that poller's state, rather than restoring the application-controlled polling described by the PR.
poller = project_client.beta.evaluators.begin_create_generation_job(
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:140
- This call leaves SDK polling enabled. A synchronous
LROPollerstarts its polling thread immediately (sdk/core/azure-core/azure/core/polling/_poller.py:225-240), so the addeddone()/status()loop merely observes SDK polling and does not demonstrate the application-controlled polling described by the PR.
This issue also appears on line 197 of the same file.
poller = project_client.beta.evaluators.begin_create_generation_job(
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py:152
- This call still defaults to SDK polling. The synchronous
LROPollerstarts a background polling thread on construction (sdk/core/azure-core/azure/core/polling/_poller.py:225-240), so the new loop observes SDK polling rather than performing the application-controlled polling described by the PR.
poller = project_client.beta.datasets.begin_create_generation_job(
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py:151
- This call still defaults to SDK polling. The synchronous
LROPollerstarts a background polling thread on construction (sdk/core/azure-core/azure/core/polling/_poller.py:225-240), so the new loop observes SDK polling rather than performing the application-controlled polling described by the PR.
poller = project_client.beta.datasets.begin_create_generation_job(
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py:131
- This call still defaults to SDK polling. A synchronous
LROPollerbegins polling in its background thread immediately, anddone()/status()only observe it. Therefore this does not demonstrate the application-controlled polling described by the PR.
poller = project_client.beta.datasets.begin_create_generation_job(
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py:167
- This call still defaults to SDK polling. A synchronous
LROPollerbegins polling in its background thread immediately, anddone()/status()only observe it. Therefore this does not demonstrate the application-controlled polling described by the PR.
poller = project_client.beta.datasets.begin_create_generation_job(
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py:173
- This call still defaults to SDK polling. A synchronous
LROPollerbegins polling in its background thread immediately, anddone()/status()only observe it. Therefore this does not demonstrate the application-controlled polling described by the PR.
poller = project_client.beta.datasets.begin_create_generation_job(
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py:182
- This call still defaults to SDK polling. A synchronous
LROPollerbegins polling in its background thread immediately, anddone()/status()only observe it. Therefore this does not demonstrate the application-controlled polling described by the PR.
poller = project_client.beta.datasets.begin_create_generation_job(
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling.py:10
- This description says the sample polls the standard LRO, but the implementation passes
polling=Falseand repeatedly callsget_optimization_job; it polls the job resource outside the SDK poller. Keep the description aligned with the behavior.
optimization job and poll its standard LRO to completion.
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling.py:78
responseis aPipelineResponse, not anOptimizationJob, as shown by the immediateresponse.http_response.json()access. The comment gives sample readers the wrong raw-response-hook callback contract.
# Since `polling=False` is set below, it is guaranteed that `capture_created_job` will be
# invoked once on the initial "201 Created" response, and `response` is of type `OptimizationJob`.
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling_async.py:81
responseis aPipelineResponse, not anOptimizationJob, as shown by the immediateresponse.http_response.text()access. The comment gives sample readers the wrong raw-response-hook callback contract.
# Since `polling=False` is set below, it is guaranteed that `capture_created_job` will be
# invoked once on the initial "201 Created" response, and `response` is of type `OptimizationJob`.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.
Suppressed comments (18)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:114
- This new async dataset sample is auto-discovered by
test_samples_async.py, but unlike its synchronous counterpart it is not excluded and this PR supplies no recording. Playback CI will attempt to execute it without a recording. Add this exact filename to the async datasetsamples_to_skiplist or commit a usable recording.
async def main() -> None:
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:10
- This description is inaccurate: the code passes
polling=Falseand repeatedly callsget_optimization_job, so it polls the job outside the standard LRO rather than polling the LRO itself.
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:78 responseis a pipeline response, not anOptimizationJob—the following lines accessresponse.http_responseand deserialize its body into that model. The current type claim misleads readers implementing their own hook.
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:30- This sample uses
begin_create_generation_job, which replacedcreate_generation_jobin azure-ai-projects 2.4.0. Advertising 2.2.0 as the minimum allows installation of versions where this API does not exist.
pip install "azure-ai-projects>=2.2.0" azure-identity openai python-dotenv aiohttp
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic.py:18
- The usage command names a file that does not exist, so copying it fails. It should reference this sample's actual filename.
python sample_optimization_job_app_polling.py
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_async.py:18
- The usage command names a file that does not exist, so copying it fails. It should reference this sample's actual filename.
python sample_optimization_job_app_polling_async.py
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:123
- This GET does not exercise the
operation_ididempotent re-submit described in the module documentation; it only retrieves the job by the ID already returned, so the assertion is tautological. Restore a secondbegin_create_generation_jobcall with the same operation ID, or remove the idempotency claim and replay terminology.
replay_job = project_client.beta.evaluators.get_generation_job(evaluator.generation_job_id)
assert replay_job.id == evaluator.generation_job_id
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_iterate.py:102
- This still delegates polling to the SDK's background
LROPoller; callingdone()andstatus()only observes that SDK polling. The PR description says this sample should demonstrate application polling outside the SDK. Usepolling=False, capture the created job ID, and pollget_generation_jobto a terminal status instead, leaving.result()as the documented built-in alternative.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
time.sleep(poll_interval_seconds)
print(f"\tstatus=`{poller.status()}`")
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:148
- This still delegates polling to the SDK's background
LROPoller; callingdone()andstatus()only observes that SDK polling. The PR description says this sample should demonstrate application polling outside the SDK. Usepolling=False, capture the created job ID, and pollget_generation_jobto a terminal status instead, leaving.result()as the documented built-in alternative.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
time.sleep(poll_interval_seconds)
print(f"\tstatus=`{poller.status()}`")
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:207
- This second flow also observes the SDK's background polling rather than polling outside the SDK as stated in the PR description. Disable SDK polling, retain the created job ID, and use
get_generation_jobuntil a terminal status.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
time.sleep(poll_interval_seconds)
print(f"\tstatus=`{poller.status()}`")
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py:170
- This still delegates polling to the SDK's background
LROPoller; callingdone()andstatus()only observes that SDK polling. The PR description says dataset samples should demonstrate application polling outside the SDK. Usepolling=False, capture the created job ID, and pollget_generation_jobto a terminal status instead.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
time.sleep(POLL_INTERVAL_SECONDS)
print(f"\tstatus=`{poller.status()}`")
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py:167
- This still delegates polling to the SDK's background
LROPoller; callingdone()andstatus()only observes that SDK polling. The PR description says dataset samples should demonstrate application polling outside the SDK. Usepolling=False, capture the created job ID, and pollget_generation_jobto a terminal status instead.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
time.sleep(POLL_INTERVAL_SECONDS)
print(f"\tstatus=`{poller.status()}`")
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py:130
- This still delegates polling to the SDK's background
LROPoller; callingdone()andstatus()only observes that SDK polling. The PR description says dataset samples should demonstrate application polling outside the SDK. Usepolling=False, capture the created job ID, and pollget_generation_jobto a terminal status instead.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
time.sleep(poll_interval_seconds)
print(f"\tstatus=`{poller.status()}`")
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py:194
- This still delegates polling to the SDK's background
LROPoller; callingdone()andstatus()only observes that SDK polling. The PR description says dataset samples should demonstrate application polling outside the SDK. Usepolling=False, capture the created job ID, and pollget_generation_jobto a terminal status instead.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
time.sleep(poll_interval_seconds)
print(f"\tstatus=`{poller.status()}`")
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py:172
- This still delegates polling to the SDK's background
LROPoller; callingdone()andstatus()only observes that SDK polling. The PR description says dataset samples should demonstrate application polling outside the SDK. Usepolling=False, capture the created job ID, and pollget_generation_jobto a terminal status instead.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
time.sleep(poll_interval_seconds)
print(f"\tstatus=`{poller.status()}`")
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py:182
- This still delegates polling to the SDK's background
LROPoller; callingdone()andstatus()only observes that SDK polling. The PR description says dataset samples should demonstrate application polling outside the SDK. Usepolling=False, capture the created job ID, and pollget_generation_jobto a terminal status instead.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
time.sleep(poll_interval_seconds)
print(f"\tstatus=`{poller.status()}`")
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:107
- This still delegates polling to the SDK's background
LROPoller; callingdone()andstatus()only observes that SDK polling. The PR description says this sample should demonstrate application polling outside the SDK. Usepolling=False, capture the created job ID, and pollget_generation_jobto a terminal status instead, leaving.result()as the documented built-in alternative.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
time.sleep(poll_interval_seconds)
print(f"\tstatus=`{poller.status()}`")
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_basic.py:126
- This still delegates polling to the SDK's background
LROPoller; callingdone()andstatus()only observes that SDK polling. The PR description says this sample should demonstrate application polling outside the SDK. Usepolling=False, capture the created job ID, and pollget_generation_jobto a terminal status instead, leaving.result()as the documented built-in alternative.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
time.sleep(poll_interval_seconds)
print(f"\tstatus=`{poller.status()}`")
[Pilot] PR Pipeline Failure AnalysisA CI pipeline failed on this pull request. Here is an automated analysis of what went wrong and how to get the build green. What failedA single async sample test is failing consistently across all platforms (macOS, Ubuntu 3.10/3.13/3.14, Windows) and all package install modes (sdist, whl, mindependency):
This PR adds a new async sample Recommended next steps
Raw pipeline analysis (azsdk ci analyze)
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Suppressed comments (9)
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_async.py:99
AsyncLROPollerdoes not start polling at construction; its polling method runs only whenresult()/wait()is awaited. Consequently,done()remains false here and this loop never reaches line 103. Startpoller.result()as a task before monitoring it, then await that task for the result.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
await asyncio.sleep(poll_interval)
print(f"status=`{poller.status()}`")
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:10
- This description says the sample polls a standard LRO, but the implementation passes
polling=Falseand manually callsget_optimization_job. Describe the application-managed polling behavior instead.
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:78 responseis a pipeline response, not anOptimizationJob; the followingresponse.http_responseaccess also demonstrates this. The comment currently teaches an incorrect callback contract.
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:181- This default selects only the blocking
await poller.result()branch, so the newly added async sample does not demonstrate the application-visible status polling that this PR restores. Default this to true (or remove the branch) so running the sample exercises its advertised polling flow.
print_poller_status = False
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic.py:18
- The usage command names a file that does not exist, so copying it fails. It should match this sample's actual filename.
python sample_optimization_job_app_polling.py
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_async.py:18
- The usage command names a file that does not exist, so copying it fails. It should match this sample's actual filename.
python sample_optimization_job_app_polling_async.py
sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py:170
- The new sample is excluded from the repository's auto-discovered async sample suite, so none of its upload, polling, result handling, or cleanup paths execute in CI. Please add the recording and enable the sample rather than merging it permanently untested.
"sample_dataset_generation_job_simpleqna_for_finetuning_async.py", # Need to add recordings
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:30
- This minimum version cannot run the sample:
begin_create_generation_jobwas introduced by the 2.4.0 rename/LRO conversion documented in CHANGELOG.md:21. Installing the advertised 2.2.x version leaves only the earlier API.
pip install "azure-ai-projects>=2.2.0" azure-identity openai python-dotenv aiohttp
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:129
- After this upload succeeds, any failure while processing the input, creating/polling the job, or inspecting outputs bypasses the deletions at the end of
main, leaving Azure OpenAI files behind. Track created IDs and perform best-effort deletion in afinallyblock so failed sample runs do not leak resources.
seed_file = await openai_client.files.create(
file=(seed_filename, io.BytesIO(SEED_REFERENCE_DOCUMENT.encode("utf-8"))),
purpose="user_data",
)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Suppressed comments (21)
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:10
- This description says the sample polls a standard LRO, but the implementation passes
polling=Falseand repeatedly callsget_optimization_job; no LRO is being polled. Keep the prior “manually poll” wording so readers understand the application owns service polling.
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:78 responseis aPipelineResponse, not anOptimizationJob(the next lines accessresponse.http_responseand deserialize the job). The type claim is misleading for readers implementing this hook.
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:123- This replacement no longer verifies idempotent re-submission:
get_generation_jobonly fetches by ID and never reusesoperation_id, despite the sample description advertising idempotent re-submits. Restore the secondbegin_create_generation_jobcall with the same operation ID and compare its result, or remove that advertised lifecycle behavior.
# Retrieve the persisted generation job using the id returned in the LRO result.
if evaluator.generation_job_id is None:
raise RuntimeError("The generated evaluator did not include a generation job id.")
replay_job = project_client.beta.evaluators.get_generation_job(evaluator.generation_job_id)
assert replay_job.id == evaluator.generation_job_id
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:207
- This second loop also only observes SDK-owned polling; the background
LROPollerperforms the service requests. To match the PR's application-polling goal, disable SDK polling and repeatedly retrieve the generation job by ID, or revise the stated scope.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:181
- The new async sample still uses the blocking SDK-polling pattern that the PR says it is replacing: awaiting
poller.result()is what starts and runsAsyncLROPollerpolling. Implement application-owned polling (for example,polling=Falseplus asyncget_generation_jobcalls) or clarify that this new sample intentionally demonstrates SDK polling.
print("Waiting for the dataset generation job to complete.")
job_result = await poller.result()
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic.py:18
- The usage command names a file that does not exist, so copying it fails. It should reference this sample's actual filename.
python sample_optimization_job_app_polling.py
sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py:170
- The newly added sample is explicitly removed from the package's auto-discovered async sample tests, so none of its API usage or cleanup behavior runs in CI. Add the recording and let
test_datasets_samplesinclude this file before merging.
"sample_dataset_generation_job_simpleqna_for_finetuning_async.py", # Need to add recordings
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_async.py:18
- The usage command names a file that does not exist, so copying it fails. It should reference this sample's actual filename.
python sample_optimization_job_app_polling_async.py
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:30
- This sample uses
begin_create_generation_job, which was introduced in 2.4.0 (CHANGELOG.md:19-22), but the installation command permits 2.2.x/2.3.x where that API is unavailable. Raise the documented minimum to 2.4.0.
pip install "azure-ai-projects>=2.2.0" azure-identity openai python-dotenv aiohttp
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:129
- After the input file is created, any processing failure, LRO exception, missing output, or retrieval failure exits before lines 209-214, leaking the input and possibly generated files in the user's project. Track created IDs and perform best-effort deletion in
finally, as the trace-generation samples do.
seed_file = await openai_client.files.create(
file=(seed_filename, io.BytesIO(SEED_REFERENCE_DOCUMENT.encode("utf-8"))),
purpose="user_data",
)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:107
- This loop only observes SDK-owned polling: synchronous
LROPollerstarts its polling thread during construction, anddone()/status()do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Usepolling=False, capture the initial job ID, and callget_generation_jobuntil terminal, or revise the stated scope.
This issue also appears on line 119 of the same file.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_iterate.py:102
- This loop only observes SDK-owned polling: synchronous
LROPollerstarts its polling thread during construction, anddone()/status()do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Usepolling=False, capture the initial job ID, and callget_generation_jobuntil terminal, or revise the stated scope.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_basic.py:126
- This loop only observes SDK-owned polling: synchronous
LROPollerstarts its polling thread during construction, anddone()/status()do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Usepolling=False, capture the initial job ID, and callget_generation_jobuntil terminal, or revise the stated scope.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:148
- This loop only observes SDK-owned polling: synchronous
LROPollerstarts its polling thread during construction, anddone()/status()do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Usepolling=False, capture the initial job ID, and callget_generation_jobuntil terminal, or revise the stated scope.
This issue also appears on line 203 of the same file.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py:170
- This loop only observes SDK-owned polling: synchronous
LROPollerstarts its polling thread during construction, anddone()/status()do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Usepolling=False, capture the initial job ID, and callget_generation_jobuntil terminal, or revise the stated scope.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(POLL_INTERVAL_SECONDS)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py:167
- This loop only observes SDK-owned polling: synchronous
LROPollerstarts its polling thread during construction, anddone()/status()do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Usepolling=False, capture the initial job ID, and callget_generation_jobuntil terminal, or revise the stated scope.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(POLL_INTERVAL_SECONDS)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py:130
- This loop only observes SDK-owned polling: synchronous
LROPollerstarts its polling thread during construction, anddone()/status()do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Usepolling=False, capture the initial job ID, and callget_generation_jobuntil terminal, or revise the stated scope.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py:194
- This loop only observes SDK-owned polling: synchronous
LROPollerstarts its polling thread during construction, anddone()/status()do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Usepolling=False, capture the initial job ID, and callget_generation_jobuntil terminal, or revise the stated scope.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py:172
- This loop only observes SDK-owned polling: synchronous
LROPollerstarts its polling thread during construction, anddone()/status()do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Usepolling=False, capture the initial job ID, and callget_generation_jobuntil terminal, or revise the stated scope.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py:182
- This loop only observes SDK-owned polling: synchronous
LROPollerstarts its polling thread during construction, anddone()/status()do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Usepolling=False, capture the initial job ID, and callget_generation_jobuntil terminal, or revise the stated scope.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic.py:97
- This changes the SDK-polling “basic” sample into another status-observation sample, even though the PR description says the basic and app-polling variants demonstrate the two distinct approaches. Keep this file as the simple blocking
poller.result()example (matching its async counterpart) and leave application polling to the advanced app-polling sample.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"status=`{poller.status()}`")
time.sleep(poll_interval)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 23 out of 23 changed files in this pull request and generated 1 comment.
Suppressed comments (17)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:207
- This second traces path has the same discrepancy:
LROPolleris already polling in its background thread, and the loop only displays SDK state. To demonstrate application polling, disable LRO polling and explicitly retrieve the generation job on each interval.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:181
- Awaiting
poller.result()delegates the entire wait to the SDK, which is the blocking behavior this PR says the dataset samples should move away from. Make this async counterpart demonstrate application polling as well (disable SDK polling, then periodically awaitget_generation_job), or clarify that it is intentionally the separate SDK-polling example.
print("Waiting for the dataset generation job to complete.")
job_result = await poller.result()
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:10
- This description is inaccurate: the code passes
polling=Falseand polls the optimization-job resource withget_optimization_job; it does not poll a standard LRO. Describe this as application/manual polling so readers understand the distinction from the SDK-managed poller samples.
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:78 - The hook argument is a pipeline response, not an
OptimizationJob(the next line accessesresponse.http_responseand then constructs the model). Correcting the type description prevents users from copying an invalid hook contract.
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:107 - This still delegates polling to the SDK: a synchronous
LROPollerstarts its background polling thread when constructed, so this loop only observes that thread. It does not restore the application-driven polling described in the PR. Disable SDK polling, retain the initial generation-job ID, and callget_generation_jobon each interval, as the advanced optimization polling sample does.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:148
- This loop only observes the synchronous poller's SDK-owned background thread; it does not perform the application polling that the PR says these evaluator samples should demonstrate. Use
polling=False, capture the initial generation-job ID, and queryget_generation_jobfrom the application loop.
This issue also appears on line 203 of the same file.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_iterate.py:102
- This still delegates polling to the SDK: a synchronous
LROPollerstarts its background polling thread when constructed, so this loop only observes that thread. It does not restore the application-driven polling described in the PR. Disable SDK polling, retain the initial generation-job ID, and callget_generation_jobon each interval.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_basic.py:126
- This still delegates polling to the SDK: a synchronous
LROPollerstarts its background polling thread when constructed, so this loop only observes that thread. It does not restore the application-driven polling described in the PR. Disable SDK polling, retain the initial generation-job ID, and callget_generation_jobon each interval.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py:170
- This still delegates polling to the SDK's synchronous background thread, so it does not restore the application-driven polling described in the PR. Disable SDK polling, retain the initial data-generation job ID, and call
get_generation_jobon each retry interval.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(POLL_INTERVAL_SECONDS)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py:167
- This still delegates polling to the SDK's synchronous background thread, so it does not restore the application-driven polling described in the PR. Disable SDK polling, retain the initial data-generation job ID, and call
get_generation_jobon each retry interval.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(POLL_INTERVAL_SECONDS)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py:130
- This loop only observes SDK-managed background polling; it is not application-driven polling. To match the PR's stated purpose, submit with SDK polling disabled, retain the initial data-generation job ID, and query
get_generation_jobon each interval.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py:194
- This loop only observes SDK-managed background polling; it is not application-driven polling. To match the PR's stated purpose, submit with SDK polling disabled, retain the initial data-generation job ID, and query
get_generation_jobon each interval.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py:172
- This loop only observes SDK-managed background polling; it is not application-driven polling. To match the PR's stated purpose, submit with SDK polling disabled, retain the initial data-generation job ID, and query
get_generation_jobon each interval.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py:182
- This loop only observes SDK-managed background polling; it is not application-driven polling. To match the PR's stated purpose, submit with SDK polling disabled, retain the initial data-generation job ID, and query
get_generation_jobon each interval.
# Optional: While SDK is polling, periodically print the job status until the job is complete
print("Periodically check job status:")
while not poller.done():
print(f"\tstatus=`{poller.status()}`")
time.sleep(poll_interval_seconds)
sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py:170
- This excludes the newly added async sample from the auto-discovered sample test suite, leaving its async LRO and resource lifecycle unexecuted in CI. Add the recording and remove this exclusion before considering the sample covered.
"sample_dataset_generation_job_simpleqna_for_finetuning_async.py", # Need to add recordings
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:213
- Cleanup runs only on the happy path. Any failure after uploading the seed file—file processing, LRO failure, output validation, or file retrieval—exits before these deletes and leaks Azure OpenAI files. Track created IDs and move best-effort deletion into a
finallyblock, as the trace-generation samples do.
for output in file_outputs:
print(f"Delete the generated Azure OpenAI file `{output.id}`.")
await openai_client.files.delete(file_id=output.id)
print(f"Delete the Azure OpenAI input file `{seed_file.id}`.")
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_cancel.py:113
done()also becomes true when the poller's background thread terminates with an exception. Because this sample never callswait()orresult(), a transport or polling failure is silently treated as completion and the sample can print a stale non-cancelled status as success. Propagate unexpected poller exceptions and explicitly validate the expected cancelled terminal state.
while not poller.done():
print(f"status=`{poller.status()}`")
time.sleep(poll_interval)
print(f"Final LRO status: `{poller.status()}`.")
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 23 out of 23 changed files in this pull request and generated no new comments.
Suppressed comments (4)
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling_async.py:76
azpysdk mypychecks this package's samples, and this empty list has no inferable element type because the nested hook'sresponseparameter is untyped. Mypy reportsvar-annotatedhere. Restore an explicitPipelineResponse[HttpRequest, AsyncHttpResponse]element type (and the corresponding imports).
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:10- This description says the sample polls the standard LRO, but the implementation sets
polling=Falseand repeatedly callsget_optimization_job. That is application-managed polling, so the description currently teaches the opposite polling mode.
This issue also appears on line 77 of the same file.
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:78
responseis a pipeline response, not anOptimizationJob(the next lines accessresponse.http_responseand deserialize that body). Correcting the type claim avoids misleading users implementing this hook.
sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py:170- This newly added async sample is explicitly removed from the auto-discovered dataset sample suite, so none of its upload, LRO, output, or cleanup paths run in CI. Please add the recording and enable the sample test before merging rather than landing the new workflow untested.
"sample_dataset_generation_job_simpleqna_for_finetuning_async.py", # Need to add recordings
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 23 out of 23 changed files in this pull request and generated no new comments.
Suppressed comments (6)
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:78
raw_response_hookreceives aPipelineResponse, not anOptimizationJob; only its HTTP response body contains the job payload. The current comment gives readers the wrong callback contract.
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:10- The sample disables SDK polling and explicitly calls
get_optimization_job, so describing it as polling the standard LRO contradicts both the implementation and the advanced app-polling purpose. Describe the manual GET-based polling instead.
This issue also appears on line 77 of the same file.
sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py:170
- This entry excludes the only execution path for the newly added async sample from the auto-discovered sample tests. As a result, the complete async LRO flow can merge without a recording or any runtime validation; add the recording and remove this skip before merging.
"sample_dataset_generation_job_simpleqna_for_finetuning_async.py", # Need to add recordings
sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:122
- Replacing the second
begin_create_generation_jobcall withget_generation_jobmeans this sample no longer exercises an idempotent re-submit, yet the module description and shared-job comment still claim it does, andreplay_jobreinforces that claim. Either restore the second begin call or rewrite those comments and rename this variable to describe retrieval.
# Retrieve the persisted generation job using the id returned in the LRO result.
assert evaluator.generation_job_id is not None, "Expected the generated evaluator to include a generation job id."
replay_job = project_client.beta.evaluators.get_generation_job(evaluator.generation_job_id)
assert replay_job.id == evaluator.generation_job_id
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_async.py:11
- This async sample does not observe the poller until it is done; it directly awaits
poller.result()and only prints the final status. Update the description to match the intentionally omitted observation loop.
Given an async AIProjectClient, this sample demonstrates how to create an
agent optimization job, observe the SDK poller until it is done, and then
get the result.
sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:129
- Once this upload succeeds, any exception while waiting for processing, running the LRO, or inspecting outputs bypasses the cleanup block and leaves remote files behind. Track created file IDs and delete them from a
finallyblock so the new sample cleans up on failure as well as success.
seed_file = await openai_client.files.create(
file=(seed_filename, io.BytesIO(SEED_REFERENCE_DOCUMENT.encode("utf-8"))),
purpose="user_data",
)
Update LRO sync samples for Agent Optimization, Dataset Generation and Evaluator Jobs to use SDK-internal polling, with observation loop in the sample to print the job status. That observation loop is commented as optional, since you can remove the loop -- and just wait for the result. But there will be no screen spew during that time, so I think it's best to loop and show some progress in the console. The async samples the observation loop does not work for some reason. CoPilot suggested a fix that I don't understand why it should be needed, so this needs further investigation and possible discussion with Kashif. So for the async samples, I omitted the observation loop -- I just await for the job result.
For the Agent Optimization case only, in addition to the above "basic" sample, I also update and kept the sample that shows how the app can do the polling itself by making the "get" calls. Rename the sample to "_job_advanced_app_polling.py" (to distinguish it from the "_job_basic.py" sample). This sample uses the
raw_response_hookcallback function in order to get the Job ID which is required in order to do the "get" call. We can do the same for the other two LRO operation groups in a different PR if needed.Still to be done:
raw_response_hookas shown in samplesamples\agents\optimization\sample_optimization_job_advanced_app_polling.pyand its async equivalent. I'll do that in a separate PR.Also: there were several samples where in the comments at the top of the sample the "Usage" line that shows how to run it used a file name different than the current file. These were all fixed to show the correct file name.